﻿using Microsoft.CSharp;
using SmartMotion.Core.Tools;
using Sunny.UI;
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;

namespace SmartMotion.Core
{
    [ReflectAble]
    public class Script : ActionItem
    {
        public Script()
        {
            DllList = new List<string>();
        }

        private IEnumerable _dllList;
        private object _objScript;

        public MethodInfo Method { get; private set; }

        [Browsable(false)]
        public string Code { get; set; }

        [Browsable(false)]
        public List<string> DllList
        {
            get { return (List<string>)_dllList; }
            set { _dllList = value; }
        }

        public override UIForm GetConfigForm()
        {
            return new FrmScriptEdit(this);
        }

        public override bool Initilize()
        {
            Stopwatch sw = Stopwatch.StartNew();
            //1创建类
            CSharpCodeProvider codeProvider = new CSharpCodeProvider();
            //2编译器
            ICodeCompiler iCodeCompiler = codeProvider.CreateCompiler();
            //3,准备要引用的Dll
            CompilerParameters dlls = new CompilerParameters();
            dlls.ReferencedAssemblies.Add("System.dll");
            dlls.ReferencedAssemblies.Add("System.core.dll");
            dlls.ReferencedAssemblies.Add("SmartMotion.Core.dll");
            dlls.ReferencedAssemblies.Add("EventMgrLib.dll");
            foreach (var dll in DllList)
            {
                dlls.ReferencedAssemblies.Add(dll);
            }

            dlls.GenerateExecutable = false;
            dlls.GenerateInMemory = true;
            //4,编译，返回结果
            CompilerResults cr = iCodeCompiler.CompileAssemblyFromSource(dlls, Code);
            if (cr.Errors.HasErrors)
            {
                foreach (CompilerError error in cr.Errors)
                {
                    Em.GetEvent<DebugMessage>().Publish($"编译{ItemName}时发生了异常{error.ErrorText}");
                }

                return false;
            }
            else
            {
                // 5.通过反射，调用的实例
                Assembly objAssembly = cr.CompiledAssembly;
                _objScript = objAssembly.CreateInstance("UserScriptLib.UserScript");
                //6.获得我们要的方法
                Method = _objScript.GetType().GetMethod("Run");
                if (Method.ReturnType == typeof(void) || Method.ReturnType != typeof(bool))
                {
                    Em.GetEvent<DebugMessage>().Publish($"编译{ItemName}时发生了异常,返回值必须为bool类型");
                }
                else
                {
                    Em.GetEvent<DebugMessage>().Publish($"编译{ItemName}成功 耗时{sw.ElapsedMilliseconds}");
                }
            }
            return true;
        }

        protected override bool RunMethod()
        {
            try
            {
                if (_objScript == null)
                {
                    Initilize();
                }
                //7,执行
                bool result = (bool)Method.Invoke(_objScript, null);
                return result;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                Em.GetEvent<DebugMessage>().Publish($"运行{ItemName}时发生了异常{e.Message}");
                return false;
            }
        }
    }
}